package com.easyaop.test.core.demo.annotation;

import com.easyaop.test.core.annotation.Log;
import com.easyaop.test.core.entity.Bean;
import com.easyaop.test.core.intercept.VirtualMethodAdvice;
import com.easyaop.test.core.listener.DebugAgentListener;
import com.easyaop.test.core.pointcut.MethodPointcut;

import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;

/**
 * @author lipan
 * @since 2025-01-20
 */
public class ByteBuddyTest2 {

    public static void main(String[] args) throws UnmodifiableClassException {
        Instrumentation install = ByteBuddyAgent.install();
        Bean bean2 = new Bean();

        MethodPointcut pointcut = MethodPointcut.forMethodPointcut(Bean.class, "getName", String.class);

//        ElementMatchers.is
        new AgentBuilder.Default()
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // 启用重定义策略
                .disableClassFormatChanges()
                .type(ElementMatchers.any())
//                .type(pointcut.getClassNameMatcher()) // 指定需要拦截的类
//                .type(ElementMatchers.nameMatches("com.easyaop.test.core.[a-z]*.Bean")) // 指定需要拦截的类
                .transform(getTransformer(pointcut))
                .with(getListener())
                .installOn(install);

        Bean bean = new Bean();
        bean.setId(1L);
        bean.setName("lp");

        final String beanName = bean.getName();
        System.out.println(beanName);
    }

    private static AgentBuilder.Transformer getTransformer(MethodPointcut pointcut) {
//        final ElementMatcher<? super MethodDescription> matcher = pointcut.getMethodSignature().getElementMatcher();
        ElementMatcher<? super MethodDescription> matcher = new ElementMatcher<MethodDescription>(
        ) {
            @Override
            public boolean matches(MethodDescription target) {
                System.out.println(target.toString());
                return false;
            }
        };
        ElementMatcher matcher2 = ElementMatchers.isAnnotatedWith(Log.class);

//        ElementMatcher matcher2=ElementMatchers.hasAnnotation(ElementMatchers.);
        return (builder, typeDescription, classLoader, javaModule, protectionDomain) -> {
//            builder.method(matcher);
            return builder.visit(Advice.to(VirtualMethodAdvice.class)
//                    .on(matcher)
                            .on(matcher2)
            );
        };
    }

    private static AgentBuilder.Listener getListener() {
        return new DebugAgentListener();
    }


}
